package com.nacos.shangtu.service.impl;

import com.nacos.shangtu.entity.po.GroupPO;
import com.nacos.shangtu.entity.po.GroupUserPO;
import com.nacos.shangtu.entity.po.UserPO;
import com.nacos.shangtu.entity.ro.GroupRo;
import com.nacos.shangtu.mapper.GroupMapper;
import com.nacos.shangtu.mapper.GroupUserMapper;
import com.nacos.shangtu.mapper.UserMapper;
import com.nacos.shangtu.service.GroupService;
import com.nacos.shangtu.util.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class GroupServiceImpl implements GroupService {

    @Autowired
    private GroupMapper groupMapper;

    @Autowired
    private GroupUserMapper groupUserMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String createGroup(String ownerId, List<String> userIds, String groupName) {
        Optional<GroupPO> optional = findGroup(userIds);
        if (optional.isPresent()) {
            return optional.get().getGroupId();
        }
        GroupPO group = new GroupPO();
        group.setGroupId(String.valueOf(SnowflakeIdWorker.generateId()));
        group.setGroupName(groupName);
        group.setCreateTime(new Date());
        group.setSearchKey(generateSearchKey(userIds));
        group.setOwnerId(ownerId);
        groupMapper.insert(group);
        log.info("create group id - {}.", group.getGroupId());
        for (String userId : userIds) {
            GroupUserPO groupUserPO = new GroupUserPO();
            groupUserPO.setGroupId(group.getGroupId());
            groupUserPO.setUserId(userId);
            groupUserMapper.insert(groupUserPO);
        }
        return group.getGroupId();
    }

    @Override
    public Optional<GroupPO> findGroup(List<String> userIds) {
        int key = generateSearchKey(userIds);
        GroupPO groupPO = groupMapper.selectBySearchKey(key);
        if (groupPO == null) {
            return Optional.empty();
        }
        return Optional.of(groupPO);
    }

    @Override
    public List<UserPO> findUsersByGroupId(String groupId) {
        List<GroupUserPO> groupUserPOS = groupUserMapper.selectByGroupId(groupId);
        List<String> userIds = groupUserPOS.stream().map(GroupUserPO::getUserId).collect(Collectors.toList());
        return userMapper.selectBatchIds(userIds);
    }

    @Override
    public Optional<GroupPO> findGroupById(String groupId) {
        GroupPO groupPO = groupMapper.selectById(groupId);
        return groupPO == null ? Optional.empty() : Optional.of(groupPO);
    }

    private int generateSearchKey(List<String> userIds) {
        return userIds.stream()
                .sorted()
                .mapToInt(String::hashCode)
                .reduce(0, (a, b) -> 31 * a + b);
    }
}
